// demo1
async function f() {
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });
  console.log('befor');
  let result = await promise; // 等待，直到 promise resolve (*)
  console.log('after')
  console.log(result); // "done!"
}

// f();

// console.log('f function executed')

// demo 2  async await monitor
async function test2() {
  // return Promise.reject('undefined  ttxxx')
  const data = getData('today')
  console.log('data: ', data);
  const data2 = await getData('tomorrow')
  console.log('data2: ', data2);
  return {
    a:2
  }
}

async function getData(str) {
  // throw new TypeError('undefined  ttxxx');
  return str + ' kardel say'
}

// test2().then(res => {
//   console.log(res);
// }).catch(e => {
//   console.log('catch', e.message)
// })
// console.log('after test2')

// demo3 实现原理
function* testG() {
  // await被编译成了yield
  const data = yield getDataAsync('today')
  console.log('data: ', data);
  const data2 = yield getData(data)
  console.log('data2: ', data2);
  return 'success'
}

async function getDataAsync(str) {
  throw new TypeError('测试一下错误');
  // return new Promise((resolve, reject) => {
  //   setTimeout(function() {
  //     resolve(str +'  '+ str);
  //   }, 1000);
  // })
  return 'getDataAsync';
}

// 高阶函数的应用，模拟async await
function co(fn) {
  return function() {
    return new Promise((resolve, reject) => {
      // 调用一次generator函数  {value, done}
      let gen = fn.apply(this, arguments);
      let index = 0;
      function step(args) {
        index++;
        console.log(`第${index}次调用`);
        let stepValue;
        try {
          stepValue = gen.next(args);
        } catch(e) {
          return reject(e.message);
        }
        console.log('co执行中', stepValue)
        const {value, done} = stepValue;
        if(done) {
          return resolve(value);
        } else {
          if(value instanceof Promise) {
            value.then(val => step(val)).catch(reason => {
              reject('ffffffffff=---------');
            })
          } else {
            step(value)
          }
          // return Promise.resolve(value).then(val => step(val))
        }
      }
      step();
    })
  }
}
let gen = co(testG)();
gen.then(res => {
  console.log('gen res ', res)
}).catch(reason => {
  console.log('reason', reason)
})